﻿using System;
using System.Collections;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Globalization;

namespace Gmantis.Controls.DataGrid.Data
{
    public interface ICollectionViewFilterExtension
    {
        // Properties
        DataGridColumnValue<DataGridFilterState>[] FilterDescriptions { get; set; }
    }

    public interface ICollectionViewGroupExtension
    {
        // Properties
        DataGridColumnValue<DataGridSortDirection>[] GroupDescriptions { get; set; }
    }

    public interface ICollectionViewSortExtension
    {
        // Properties
        DataGridColumnValue<DataGridSortDirection>[] SortDescriptions { get; set; }
    }

    public class BaseCollectionView : ICollectionView, IEnumerable, INotifyCollectionChanged, IPagedCollectionView, IEditableCollectionView
    {
        // Fields
        private ICollectionView _collectionView;

        // Events
        public event NotifyCollectionChangedEventHandler CollectionChanged;

        public event EventHandler CurrentChanged;

        public event CurrentChangingEventHandler CurrentChanging;

        public event EventHandler<EventArgs> PageChanged;

        public event EventHandler<PageChangingEventArgs> PageChanging;

        // Methods
        public BaseCollectionView()
        {
        }

        public BaseCollectionView(IEnumerable collectionView)
        {
            this.CollectionView = collectionView as ICollectionView;
        }

        public virtual object AddNew()
        {
            return this.EditableCollectionView.AddNew();
        }

        public virtual void CancelEdit()
        {
            this.EditableCollectionView.CancelEdit();
        }

        public virtual void CancelNew()
        {
            this.EditableCollectionView.CancelNew();
        }

        private void CollectionView_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            if (this.CollectionChanged != null)
            {
                this.CollectionChanged(this, e);
            }
        }

        private void CollectionView_CurrentChanged(object sender, EventArgs e)
        {
            if (this.CurrentChanged != null)
            {
                this.CurrentChanged(this, e);
            }
        }

        private void CollectionView_CurrentChanging(object sender, CurrentChangingEventArgs e)
        {
            if (this.CurrentChanging != null)
            {
                this.CurrentChanging(this, e);
            }
        }

        public virtual void CommitEdit()
        {
            this.EditableCollectionView.CommitEdit();
        }

        public virtual void CommitNew()
        {
            this.EditableCollectionView.CommitNew();
        }

        public virtual bool Contains(object item)
        {
            return this.CollectionView.Contains(item);
        }

        public virtual IDisposable DeferRefresh()
        {
            return this.CollectionView.DeferRefresh();
        }

        public virtual void EditItem(object item)
        {
            this.EditableCollectionView.EditItem(item);
        }

        ~BaseCollectionView()
        {
            this.UnWireEvents();
        }

        public virtual IEnumerator GetEnumerator()
        {
            return this.CollectionView.GetEnumerator();
        }

        public virtual bool MoveCurrentTo(object item)
        {
            return this.CollectionView.MoveCurrentTo(item);
        }

        public virtual bool MoveCurrentToFirst()
        {
            return this.CollectionView.MoveCurrentToFirst();
        }

        public virtual bool MoveCurrentToLast()
        {
            return this.CollectionView.MoveCurrentToLast();
        }

        public virtual bool MoveCurrentToNext()
        {
            return this.CollectionView.MoveCurrentToNext();
        }

        public virtual bool MoveCurrentToPosition(int position)
        {
            return this.CollectionView.MoveCurrentToPosition(position);
        }

        public virtual bool MoveCurrentToPrevious()
        {
            return this.CollectionView.MoveCurrentToPrevious();
        }

        public virtual bool MoveToFirstPage()
        {
            return this.PagedCollectionView.MoveToFirstPage();
        }

        public virtual bool MoveToLastPage()
        {
            return this.PagedCollectionView.MoveToLastPage();
        }

        public virtual bool MoveToNextPage()
        {
            return this.PagedCollectionView.MoveToNextPage();
        }

        public virtual bool MoveToPage(int pageIndex)
        {
            return this.PagedCollectionView.MoveToPage(pageIndex);
        }

        public virtual bool MoveToPreviousPage()
        {
            return this.PagedCollectionView.MoveToPreviousPage();
        }

        private void PagedCollectionView_PageChanged(object sender, EventArgs e)
        {
            if (this.PageChanged != null)
            {
                this.PageChanged(this, e);
            }
        }

        private void PagedCollectionView_PageChanging(object sender, PageChangingEventArgs e)
        {
            if (this.PageChanging != null)
            {
                this.PageChanging(this, e);
            }
        }

        public virtual void Refresh()
        {
            this.CollectionView.Refresh();
        }

        public virtual void Remove(object item)
        {
            this.EditableCollectionView.Remove(item);
        }

        public virtual void RemoveAt(int index)
        {
            this.EditableCollectionView.RemoveAt(index);
        }

        private void UnWireEvents()
        {
            this.CollectionView.CollectionChanged -= new NotifyCollectionChangedEventHandler(this.CollectionView_CollectionChanged);
            this.CollectionView.CurrentChanging -= new CurrentChangingEventHandler(this.CollectionView_CurrentChanging);
            this.CollectionView.CurrentChanged -= new EventHandler(this.CollectionView_CurrentChanged);
            this.PagedCollectionView.PageChanging -= new EventHandler<PageChangingEventArgs>(this.PagedCollectionView_PageChanging);
            this.PagedCollectionView.PageChanged -= new EventHandler<EventArgs>(this.PagedCollectionView_PageChanged);
        }

        private void WireEvents()
        {
            this.CollectionView.CollectionChanged += new NotifyCollectionChangedEventHandler(this.CollectionView_CollectionChanged);
            this.CollectionView.CurrentChanging += new CurrentChangingEventHandler(this.CollectionView_CurrentChanging);
            this.CollectionView.CurrentChanged += new EventHandler(this.CollectionView_CurrentChanged);
            this.PagedCollectionView.PageChanging += new EventHandler<PageChangingEventArgs>(this.PagedCollectionView_PageChanging);
            this.PagedCollectionView.PageChanged += new EventHandler<EventArgs>(this.PagedCollectionView_PageChanged);
        }

        // Properties
        public virtual bool CanAddNew
        {
            get
            {
                return this.EditableCollectionView.CanAddNew;
            }
        }

        public virtual bool CanCancelEdit
        {
            get
            {
                return this.EditableCollectionView.CanCancelEdit;
            }
        }

        public virtual bool CanChangePage
        {
            get
            {
                return this.PagedCollectionView.CanChangePage;
            }
        }

        public virtual bool CanFilter
        {
            get
            {
                return this.CollectionView.CanFilter;
            }
        }

        public virtual bool CanGroup
        {
            get
            {
                return this.CollectionView.CanGroup;
            }
        }

        public virtual bool CanRemove
        {
            get
            {
                return this.EditableCollectionView.CanRemove;
            }
        }

        public virtual bool CanSort
        {
            get
            {
                return this.CollectionView.CanSort;
            }
        }

        public ICollectionView CollectionView
        {
            get
            {
                return this._collectionView;
            }
            set
            {
                if (this._collectionView != null)
                {
                    this.UnWireEvents();
                }
                this._collectionView = value;
                this.PagedCollectionView = value as IPagedCollectionView;
                this.EditableCollectionView = value as IEditableCollectionView;
                if (((this.CollectionView == null) || (this.PagedCollectionView == null)) || (this.EditableCollectionView == null))
                {
                    throw new ArgumentNullException("collectionView");
                }
                this.WireEvents();
                this.CollectionView_CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
            }
        }

        public virtual CultureInfo Culture
        {
            get
            {
                return this.CollectionView.Culture;
            }
            set
            {
                this.CollectionView.Culture = value;
            }
        }

        public virtual object CurrentAddItem
        {
            get
            {
                return this.EditableCollectionView.CurrentAddItem;
            }
        }

        public virtual object CurrentEditItem
        {
            get
            {
                return this.EditableCollectionView.CurrentEditItem;
            }
        }

        public virtual object CurrentItem
        {
            get
            {
                return this.CollectionView.CurrentItem;
            }
        }

        public virtual int CurrentPosition
        {
            get
            {
                return this.CollectionView.CurrentPosition;
            }
        }

        public IEditableCollectionView EditableCollectionView { get; private set; }

        public virtual Predicate<object> Filter
        {
            get
            {
                return this.CollectionView.Filter;
            }
            set
            {
                this.CollectionView.Filter = value;
            }
        }

        public virtual System.Collections.ObjectModel.ObservableCollection<GroupDescription> GroupDescriptions
        {
            get
            {
                return this.CollectionView.GroupDescriptions;
            }
        }

        public virtual ReadOnlyObservableCollection<object> Groups
        {
            get
            {
                return this.CollectionView.Groups;
            }
        }

        public virtual bool IsAddingNew
        {
            get
            {
                return this.EditableCollectionView.IsAddingNew;
            }
        }

        public virtual bool IsCurrentAfterLast
        {
            get
            {
                return this.CollectionView.IsCurrentAfterLast;
            }
        }

        public virtual bool IsCurrentBeforeFirst
        {
            get
            {
                return this.CollectionView.IsCurrentBeforeFirst;
            }
        }

        public virtual bool IsEditingItem
        {
            get
            {
                return this.EditableCollectionView.IsEditingItem;
            }
        }

        public virtual bool IsEmpty
        {
            get
            {
                return this.CollectionView.IsEmpty;
            }
        }

        public virtual bool IsPageChanging
        {
            get
            {
                return this.PagedCollectionView.IsPageChanging;
            }
        }

        public virtual int ItemCount
        {
            get
            {
                return this.PagedCollectionView.ItemCount;
            }
        }

        public virtual NewItemPlaceholderPosition NewItemPlaceholderPosition
        {
            get
            {
                return this.EditableCollectionView.NewItemPlaceholderPosition;
            }
            set
            {
                this.EditableCollectionView.NewItemPlaceholderPosition = value;
            }
        }

        public IPagedCollectionView PagedCollectionView { get; private set; }

        public virtual int PageIndex
        {
            get
            {
                return this.PagedCollectionView.PageIndex;
            }
        }

        public virtual int PageSize
        {
            get
            {
                return this.PagedCollectionView.PageSize;
            }
            set
            {
                this.PagedCollectionView.PageSize = value;
            }
        }

        public virtual SortDescriptionCollection SortDescriptions
        {
            get
            {
                return this.CollectionView.SortDescriptions;
            }
        }

        public virtual IEnumerable SourceCollection
        {
            get
            {
                return this.CollectionView.SourceCollection;
            }
        }

        public virtual int TotalItemCount
        {
            get
            {
                return this.PagedCollectionView.TotalItemCount;
            }
        }
    }
}
